home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / util / cli / fsearch.lha / Rep_SRC / rep.c next >
Encoding:
C/C++ Source or Header  |  1999-10-16  |  6.4 KB  |  255 lines

  1.  
  2. /******** rep.c by Dimitri C. Keletsekis *****************************
  3.  
  4. ***    This code compiles into a small executable re-entrant CLI
  5. ***    command for replacing strings in files. It can be compiled
  6. ***    with SAS C 6.50+.  The SCOPTIONS file is included. Just do
  7. ***    <sc rep link> to produce it.
  8. ***
  9. ***    It's may not be the best, it may not be the fastest, but it
  10. ***    works..
  11. ***
  12. ***    It uses the NOSTARTUP compiler option which means that it
  13. ***    compiles without *any* start-up code from the compiler,
  14. ***    resulting in a smaller, sexier executable.
  15.  
  16. *************************************************************************/
  17.  
  18. #define __USE_SYSBASE;
  19. #include <exec/exec.h>
  20. #include <exec/types.h>
  21. #include <exec/execbase.h>
  22. #include <exec/memory.h>
  23. #include <dos/dosextens.h>
  24. #include <dos/rdargs.h>
  25. #include <dos/dostags.h>
  26.  
  27. #include <string.h>
  28. #include <stdio.h>
  29. #include <ctype.h>
  30. #include <dos.h>
  31.  
  32. #include <proto/dos.h>
  33. #include <proto/exec.h>
  34.  
  35. #define THISPROC     ((struct Process *)(SysBase->ThisTask))
  36. #define Result2(x) THISPROC->pr_Result2 = x
  37.  
  38. static const char VERSION[] = "\0$VER: Rep 1.4 (D.Keletsekis 2/2/99)";
  39.  
  40. // prototypes
  41. LONG rep (void);
  42. LONG parse (UBYTE *);
  43.  
  44. LONG rep(void)
  45. {
  46.     struct ExecBase *SysBase = (*((struct ExecBase **) 4));
  47.     struct DosLibrary  *DOSBase=NULL;
  48.     struct RDArgs *rdargs = NULL;
  49.     UBYTE *file, *repstr, *dest;
  50.     UBYTE upstr[256], *str;            // string buffer for case insensitive
  51.     LONG rc;
  52.     long args[5];
  53.     struct FileInfoBlock *fib=NULL;
  54.     UBYTE *buff=NULL;
  55.     BPTR fp;
  56.     LONG buffsize, sz;
  57.     int err = 0, c;
  58.     register UBYTE *p, *d, *t, *u;
  59.     UBYTE *endfile=0;
  60.     BOOL INSENSITIVE = 0;
  61.     LONG lstr, lrep;   // string lengths
  62.  
  63.     rc = 10;   /* return code */
  64.  
  65.     if (!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 36L)))
  66.     {    Result2(ERROR_INVALID_RESIDENT_LIBRARY);
  67.         goto endprog;
  68.     }
  69.  
  70.     memset((char *)args, 0, sizeof(args));
  71.     rdargs = ReadArgs("FILE/A,STRING/A,NEWSTRING/A,NEWFILE,I=INSENSITIVE/S", args, NULL);
  72.     if (!rdargs)
  73.     {    PrintFault (IoErr(), "REP by dck@hol.gr\nERROR");
  74.         goto endprog;
  75.     }
  76.  
  77.     file   = (UBYTE *)args[0];
  78.     str    = (UBYTE *)args[1];
  79.     repstr = (UBYTE *)args[2];
  80.     if (args[3]) dest = (UBYTE *)args[3]; else dest = file;
  81.     if (args[4]) INSENSITIVE = 1;
  82.  
  83.     // parse strings for hex, decimals etc
  84.     if (((lstr = parse (str)) == -1) || ((lrep = parse (repstr)) == -1))
  85.     {  PutStr ("Error parsing string\n");
  86.        goto endprog;
  87.     }
  88.     // max size of upstr buffer
  89.     if (lstr > 250)
  90.     {  PutStr ("String too long\n");
  91.        goto endprog;
  92.     }
  93.  
  94.     /*------------------------------ read file ------------------------*/
  95.  
  96.     if (!(fp = Open (file, MODE_OLDFILE))) 
  97.     {  PutStr ("Could not open file\n");
  98.        goto endprog;
  99.     }
  100.  
  101.     if (fib = (struct FileInfoBlock *)AllocVec(sizeof(struct FileInfoBlock), MEMF_CLEAR))
  102.     {   if (ExamineFH(fp, fib))
  103.         {   buffsize = fib->fib_Size;
  104.             if (buff = (unsigned char *)AllocVec(buffsize + 32, MEMF_CLEAR))
  105.             {   sz = Read (fp, buff, buffsize);
  106.                 if (sz != buffsize) ++err;
  107.                 endfile = &buff[sz];
  108.             }
  109.         }
  110.         FreeVec (fib);
  111.     }
  112.     Close (fp);
  113.  
  114.     if (err)
  115.     {  PutStr ("Error reading file\n");
  116.        goto endprog;
  117.     }
  118.     else if (!buff)
  119.     {  PutStr ("No memory!\n");
  120.        goto endprog;
  121.     }
  122.  
  123.     // ------------------------- prepare.. -------------------
  124.  
  125.     if (!(fp = Open (dest, MODE_NEWFILE)))
  126.     {  PutStr ("Error writing file\n");
  127.        goto endprog;
  128.     }
  129.     p = buff;
  130.  
  131.     // copy to upstr buffer - not with strcpy since there may be NULLs
  132.     for (c=0; c<lstr; ++c) upstr[c] = str[c];
  133.     upstr[c] = 0;
  134.  
  135.     if (INSENSITIVE)
  136.     {  d = str;
  137.        u = upstr;               // make lower/upper case buffers
  138.        for (c=0; c<lstr; ++c)
  139.        {  if ((*d >= 'A') && (*d < 'a'))  *d = ((*d) + ('a' - 'A'));
  140.           if ((*u >= 'a') && (*u <= 'z')) *u = ((*u) - ('a' - 'A'));
  141.           ++d; ++u;
  142.        }
  143.     }
  144.  
  145.     // -------------------- DO THE CHACHA ------------------
  146.  
  147.     while (p < endfile)
  148.     {
  149.        if ((*p == *str) || (*p == *upstr))
  150.        {   t = p;
  151.            d = str;
  152.            u = upstr;
  153.            for (c = 0; (c < lstr) && ((*d == *t) || (*u == *t)); ++c)
  154.            {   ++t; ++d; ++u;  }
  155.            if (c == lstr)           // found it
  156.            {   --t;
  157.                p = t;
  158.                for (c = 0; c < lrep; ++c)
  159.                {   if (EOF == (int)(FPutC (fp, repstr[c]))) goto endflag;
  160.                }
  161.            }
  162.            else
  163.                if (EOF == (int)(FPutC (fp, *p))) goto endflag;
  164.         }
  165.         else
  166.            if (EOF == (int)(FPutC (fp, *p))) goto endflag;
  167.  
  168.         ++p;
  169.     }
  170.     rc = 0;
  171.     goto endnoflag;  /* i.e. skip error report */
  172.  
  173.     endflag:
  174.     PutStr ("Error writing file\n");
  175.  
  176.     endnoflag:
  177.     Close (fp);
  178.  
  179.     endprog :
  180.     if (rdargs)  FreeArgs (rdargs);
  181.     if (buff)    FreeVec (buff);
  182.     if (DOSBase) CloseLibrary((struct Library *)DOSBase);
  183.     return (rc);
  184. }
  185.  
  186. // --------------------------------------------------------------
  187. // Parse a string, overwriting it.
  188. // Return length (may contain NULLs) 
  189. // Return -1 for error
  190. // --------------------------------------------------------------
  191.  
  192. LONG parse (UBYTE *str)
  193. {
  194.     LONG  len = 0, c;
  195.     int   x;
  196.     UBYTE *p, *s;
  197.     UBYTE hx[5];
  198.  
  199.     if (!str) return (-1);
  200.     if (!str[0]) return (0);
  201.     s = p = str;
  202.  
  203.     while (*p)
  204.     {  
  205.         if (*p == '\\')   // start of special characters
  206.         {   ++p;
  207.             switch (*p)
  208.             {   case 'n' : *s = '\n'; ++s; ++p; break;
  209.                 case 'r' : *s = '\r'; ++s; ++p; break;
  210.                 case 't' : *s = '\t'; ++s; ++p; break;
  211.                 case '\"': *s = '\"'; ++s; ++p; break;
  212.                 case '\'': *s = '\''; ++s; ++p; break;
  213.                 case '\\': *s = '\\'; ++s; ++p; break;
  214.  
  215.                 case 'X' :
  216.                 case 'x' : // hex
  217.                      ++p;
  218.                      while (*p && (*p != '\\'))
  219.                      {   hx[0] = *p; ++p;
  220.                          hx[1] = *p; ++p; hx[2] = 0;
  221.                          if ((stch_i(hx, &x)) != 2)
  222.                              return (-1);
  223.                          *s = (UBYTE)x;
  224.                          ++s;
  225.                      }
  226.                      if (*p == '\\') ++p;
  227.                      break;
  228.  
  229.                 case '#' : // decimal
  230.                      ++p; 
  231.                      c = (*p - '0'); // do first
  232.                      ++p;
  233.                      while (*p && (*p!='\\') && (*p>='0') && (*p<='9')) // do rest
  234.                      {   c *= 10;
  235.                          c += (LONG)(*p - '0');
  236.                          ++p;
  237.                      }
  238.                      *s = (UBYTE)c; 
  239.                      ++s;
  240.                      if (*p == '\\') ++p;
  241.                      break;
  242.  
  243.                default : *s = *p; ++s; ++p; break;
  244.             };
  245.         }
  246.         else
  247.         {   *s = *p; ++s; ++p;
  248.         }
  249.     }
  250.     *s = 0;                 // terminating null
  251.     len = s - str;
  252.     return (len);           // return new length
  253. }
  254.  
  255.